//
//  BlePlugin.m
//  flutter_bluetooth_plugin
//
//  Created by CoinBig on 2021/3/25.
//

#import "BlePlugin.h"
#import <CoreBluetooth/CoreBluetooth.h>

static FlutterMethodChannel* channel;

@interface BlePlugin () <CBCentralManagerDelegate,CBPeripheralDelegate>

// 中心管理者(管理设备的扫描和连接)
@property (nonatomic, strong) CBCentralManager *centralManager;

// 外设状态
@property (nonatomic, assign) NSInteger peripheralState;

// 当前连接的蓝牙外设
@property (nonatomic, strong) CBPeripheral *peripheral;

// 所有的蓝牙设备集合
@property (nonatomic, strong) NSMutableArray *peripheralDataArray;

@property (nonatomic, strong) CBCharacteristic *readCharacteristic; //用来读取信息的特征 0xFFE3
// 扫描到的特征
@property (nonatomic, strong) CBCharacteristic *characteristic;

@end

@implementation BlePlugin

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    NSLog(@"registerWithRegistrar*****");
    channel = [FlutterMethodChannel
               methodChannelWithName:@"flutter_bluetooth_plugin"
               binaryMessenger:[registrar messenger]];
    BlePlugin* instance = [[BlePlugin alloc] initWithChannel:registrar];
    [registrar addMethodCallDelegate:instance channel:channel];
    NSLog(@"registerWithRegistrar------");
}

// 注册eventchannel事件
- (instancetype)initWithChannel:(NSObject<FlutterPluginRegistrar> *)registrar {
    // 初始化变量
    FlutterEventChannel * eventChannel = [FlutterEventChannel eventChannelWithName:@"flutter_bluetooth_plugin/state" binaryMessenger:[registrar messenger]];
    [eventChannel setStreamHandler:self];
    [self initBluetooth];
    return self;
}

#pragma mark - FlutterStreamHandler
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(FlutterEventSink)events{
    NSLog(@"onListenWithArguments********");
    if(events){
        _eventSink = events;
    }
    return nil;
}

- (FlutterError * _Nullable)onCancelWithArguments:(id _Nullable)arguments{
    _eventSink = nil;
    return nil;
}

- (void)initBluetooth {
    NSLog(@"initBluetooth");
    //初始化 蓝牙库
    _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}

// 状态更新时调用
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    switch (central.state) {
        case CBManagerStateUnknown:{
            self.peripheralState = central.state;
        }
            break;
        case CBManagerStateResetting:
        {
            self.peripheralState = central.state;
        }
            break;
        case CBManagerStateUnsupported:
        {
            
            self.peripheralState = central.state;
        }
            break;
        case CBManagerStateUnauthorized:
        {
            self.peripheralState = central.state;
        }
            break;
        case CBManagerStatePoweredOff:
        {
            self.peripheralState = central.state;
        }
            break;
        case CBManagerStatePoweredOn:
        {
            self.peripheralState = central.state;
        }
            break;
        default:
            break;
    }
}

- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
{
    NSLog(@"handleMethodCall=======%@",call.method);
    //打开蓝牙
    if ([@"turnOn" isEqualToString:call.method]) {
        
        if (self.peripheralState == 0) {
            result([self sendType:0 message:@"蓝牙设备状态未知"]);
        }
        else if (self.peripheralState == 1) {
            result([self sendType:1 message:@"蓝牙状态已重置"]);
        }
        else if (self.peripheralState == 2) {
            result([self sendType:2 message:@"设备不支持蓝牙"]);
        }
        else if (self.peripheralState == 3) {
            result([self sendType:3 message:@"蓝牙未授权"]);
        }
        else if (self.peripheralState == 5) {
            result([self sendType:200 message:@"打开蓝牙"]);
        }
        NSLog(@"status=======%@",[self sendType:200 message:@"打开蓝牙"]);
    }
    else if ([@"turnOff" isEqualToString:call.method]) {
        //停止扫描
        [self.centralManager stopScan];
        //断开连接
        [self.centralManager cancelPeripheralConnection:self.peripheral];
        result([self sendType:200 message:@"关闭蓝牙"]);
        NSLog(@"status=======%@",[self sendType:200 message:@"关闭蓝牙"]);
    }
    else if ([@"startScan" isEqualToString:call.method]) {
        [self.centralManager scanForPeripheralsWithServices:nil options:nil];
        result([self sendType:200 message:@"开始扫描"]);
        NSLog(@"status=======%@",[self sendType:200 message:@"开始扫描"]);
    }
    else if ([@"stopScan" isEqualToString:call.method]) {
        //停止扫描
        [self.centralManager stopScan];
        result([self sendType:200 message:@"暂停扫描"]);
        NSLog(@"status=======%@",[self sendType:200 message:@"暂停扫描"]);
    }
    else if ([@"connectDevice" isEqualToString:call.method]) {
        NSMutableDictionary *dic =  call.arguments;
        NSString *address = [dic objectForKey:@"connectDeviceAddress"];
        NSArray *peripherals = [self.peripheralDataArray valueForKey:@"device"];
        
        // 蓝牙连接
        for (CBPeripheral* peripheral in peripherals) {
            if([peripheral.identifier.UUIDString isEqualToString:address]){
                NSLog(@"ios 在数组中找到了对应的peripheral=================");
                [self.centralManager stopScan];
                [self.centralManager connectPeripheral:peripheral options:nil];
                self.peripheral = peripheral;
            }
        }
        NSLog(@"connectDevice -- %@",dic);
        result([self sendType:200 message:@"连接成功"]);
        NSLog(@"status=======%@",[self sendType:200 message:@"连接成功"]);
    }
    else if ([@"sendMsg" isEqualToString:call.method]) {
        NSMutableDictionary *dic =  call.arguments;
        NSString *msg = [dic objectForKey:@"msg"];
        NSStringEncoding gbkEncoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
        NSData *data = [msg dataUsingEncoding:gbkEncoding];
        if (self.characteristic.properties & CBCharacteristicPropertyWrite) {
            [self writeData:data];
            NSLog(@"status=======%@",[self sendType:200 message:@"发送成功"]);
        } else {
            NSLog(@"status=======%@",[self sendType:400 message:@"发送失败"]);
        }
    }
}

// 连接某个设备
- (void)connectPeripheral:(CBPeripheral*)peripheral {
    
    NSMutableDictionary *dataDic = [[NSMutableDictionary alloc] init];
    
    if (@available(iOS 9.0, *)) {
        if ([peripheral state] == CBPeripheralStateDisconnecting) {
            [dataDic setValue:@(3) forKey:@"state"];
        }
    }
    else
    {
        if ([peripheral state] == CBPeripheralStateDisconnected) {
            [dataDic setValue:@(2) forKey:@"state"];
        } else if ([peripheral state] == CBPeripheralStateConnecting) {
            [dataDic setValue:@(1) forKey:@"state"];
        } else if ([peripheral state] == CBPeripheralStateConnected) {
            [dataDic setValue:@(0) forKey:@"state"];
        }
    }
    [channel invokeMethod:@"blueState" arguments:dataDic];
}

// 扫描到设备的监听
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {
    self.peripheral = peripheral;
    // 处理发现的蓝牙设备
    [self addBlutoothDevice:peripheral advertisementData:advertisementData RSSI:RSSI];
}

// 扫描到的蓝牙处理
- (void)addBlutoothDevice:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
    NSString *name  = [advertisementData objectForKey:@"kCBAdvDataLocalName"];
    NSLog(@"搜索到了设备LocalName:%@",name);
    NSArray *peripherals = [self.peripheralDataArray valueForKey:@"peripheral"];
    if(![peripherals containsObject:peripheral]) {
        NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:peripherals.count inSection:0];
        [indexPaths addObject:indexPath];
        NSMutableDictionary *item = [[NSMutableDictionary alloc] init];
        [item setValue:name forKey:@"name"];
        [item setValue:RSSI forKey:@"rssi"];
        [item setValue:peripheral.identifier.UUIDString forKey:@"address"];
        [item setValue:peripheral forKey:@"device"];
        [self.peripheralDataArray addObject:item];
    } else {
        // 已经发现的不再添加进去
        return;
    }
    // 处理扫描到的蓝牙数据，发送给我上层
//    NSMutableArray * temp = [[NSMutableArray alloc]init];
    for (NSMutableDictionary * peripheral in self.peripheralDataArray) {
        NSString * name = [peripheral objectForKey:@"name"];
        NSString *rssi = [peripheral objectForKey:@"rssi"];
        NSString *mac = [peripheral objectForKey:@"address"];
        // value -> key 结构
        NSDictionary *dict =[NSDictionary dictionaryWithObjectsAndKeys:name, @"name", rssi, @"rssi", mac, @"address",nil];
        NSData * jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
        NSLog(@"json字典里面的内容为--》%@", jsonData);
        NSString *text = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
        NSLog(@"text -- %@",text);
        NSMutableDictionary *dataDic = [[NSMutableDictionary alloc] init];
        [dataDic setValue:text forKey:@"data"];
        [channel invokeMethod:@"deviceResultListener" arguments:dataDic];
    }
}

/**
 连接成功
 
 @param central 中心管理者
 @param peripheral 连接成功的设备
 */
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    NSLog(@"连接设备:%@成功",peripheral.name);
    if (peripheral) {
        // 设置设备的代理
        peripheral.delegate = self;
        // services:传入nil  代表扫描所有服务
        // 遍历所有的服务
        [peripheral discoverServices:@[[CBUUID UUIDWithString:@"FFF2"]]];
    }
    [channel invokeMethod:@"blueState" arguments:0];
}

/**
 连接失败
 @param central 中心管理者
 @param peripheral 连接失败的设备
 @param error 错误信息
 */
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"%@",@"连接失败");
    NSMutableDictionary *dataDic = [[NSMutableDictionary alloc] init];
    [dataDic setValue:@(2) forKey:@"state"];
    [channel invokeMethod:@"blueState" arguments:dataDic];
}

/**
 连接断开
 @param central 中心管理者
 @param peripheral 连接断开的设备
 @param error 错误信息
 */
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"%@   ----    %@",@"断开连接",error.description);
    NSMutableDictionary *dataDic = [[NSMutableDictionary alloc] init];
    [dataDic setValue:@(2) forKey:@"state"];
    [channel invokeMethod:@"blueState" arguments:dataDic];
}

/**
 扫描到服务
 @param peripheral 服务对应的设备
 @param error 扫描错误信息
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    // 遍历所有的服务
    for (CBService *service in peripheral.services)
    {
        if ([service.UUID isEqual:[CBUUID UUIDWithString:@"FFF2"]]) {
            CBUUID *writeUUID = [CBUUID UUIDWithString:@"FFE3"];
            
            CBUUID *notifyUUID = [CBUUID UUIDWithString:@"FFE4"];
            
            [peripheral discoverCharacteristics:@[writeUUID, notifyUUID] forService:service];
        }
        NSLog(@"服务:%@",service.UUID.UUIDString);
    }
}

/**
 扫描到对应的特征
 @param peripheral 设备
 @param service 特征对应的服务
 @param error 错误信息
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    if (!error) {
        
        NSArray *characteristicArray = service.characteristics;
        
        if (characteristicArray.count > 1) {
            
            self.readCharacteristic = characteristicArray[0];
            
            self.characteristic = characteristicArray[1];
            
            // 通知使能，YESenable notification only,NOdisable notifications and indications
            
            [peripheral setNotifyValue:YES forCharacteristic:self.readCharacteristic];
            
        }
    } else {
        NSLog(@"Discover Charactertics Error : %@", error);
    }
}

#pragma mark - 获取数据
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    
    NSStringEncoding gbkEncoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
    NSString *result = [[NSString alloc] initWithData:characteristic.value encoding:gbkEncoding];
    NSLog(@"result -- %@",result);
    
    NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
    [dic setValue:result forKey:@"message"];
    [channel invokeMethod:@"messageListener" arguments:dic];
    NSLog(@"dic ---- %@",dic);
}

#pragma mark 数据写入成功回调

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"%s, line = %d, error = %@",__FUNCTION__,__LINE__,error.description);
    }
    NSLog(@"写入成功");
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    if (error) {
        NSLog(@"%s, line = %d, error = %@",__FUNCTION__,__LINE__,error.description);
    }
    else
    {
        NSLog(@"descriptors  -- %@",characteristic.descriptors);
    }
}

//MARK: 分段写入
- (void)writeData:(NSData *)data
{
    // 判断能写入字节的最大长度
    int maxValue;
    if (@available(iOS 9.0, *)) {
        // type:这里和上面一样，
        maxValue =(int)[self.peripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithoutResponse];
    } else {
        // 默认是20字节
        maxValue =20;
    }
    NSLog(@"%i",maxValue);
    for (int i = 0; i < [data length]; i += maxValue) {
        // 预加 最大包长度，如果依然小于总数据长度，可以取最大包数据大小
        if ((i + maxValue) < [data length]) {
            NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, maxValue];
            NSData *subData = [data subdataWithRange:NSRangeFromString(rangeStr)];
            [self sendDataToBLE:subData];
            // 根据接收模块的处理能力做相应延时
            usleep(10 * 1000);
        }
        else {
            NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, (int)([data length] - i)];
            NSData *subData = [data subdataWithRange:NSRangeFromString(rangeStr)];
            [self sendDataToBLE:subData];
            usleep(10 * 1000);
        }
    }
}

//MARK: 发送数据
-(void)sendDataToBLE:(NSData *)data{
    if(nil != self.characteristic){
        [self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
    }
}

// 发送提示封装
- (NSString *)sendType:(NSInteger)code message:(NSString *)message {
    NSDictionary *param = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInteger:code],@"code",message,@"msg", nil];
    NSString *jsonString = [self convertToJsonData:param];
    return jsonString;
}

// NSDictionary转json封装
- (NSString *)convertToJsonData:(NSDictionary *)dict {
    
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];
    NSString *jsonString;
    if (!jsonData) {
        NSLog(@"%@",error);
    } else {
        jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    NSMutableString *mutStr = [NSMutableString stringWithString:jsonString];
    return mutStr;
}

- (NSMutableArray *)peripheralDataArray
{
    if (!_peripheralDataArray) {
        _peripheralDataArray = [[NSMutableArray alloc] init];
    }
    return _peripheralDataArray;
}

@end
